﻿//#defin INI

using Demo_串口.Service;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

namespace Demo_串口.Model
{
    class ModelMainWindow : NotifyPropertyChange//逻辑
    {
        #region 建立单例
        private static ModelMainWindow uniqueInstance;
        private static readonly object locker = new object();
        public static ModelMainWindow GetInstance()
        {
            if (uniqueInstance == null)
            {
                lock (locker)
                {
                    if (uniqueInstance == null)
                    {
                        uniqueInstance = new ModelMainWindow();
                    }
                }
            }
            return uniqueInstance;
        }
        #endregion

        public ModelMainWindow()
        {
            LSPInit();

            InitAutoSendTimer();//自动发送的时钟实现

        }

        #region 读入INI

        public void INIRead()
        {
            SPPort = CsINIForSp.GetInstance().ReadComValue("SerialPort", "ComPort");
            SPBaudRate = int.Parse(CsINIForSp.GetInstance().ReadComValue("SerialPort", "BaudRate"));
            SPDataBits = int.Parse(CsINIForSp.GetInstance().ReadComValue("SerialPort", "DataBits"));
            SPStopBits = double.Parse(CsINIForSp.GetInstance().ReadComValue("SerialPort", "StopBits"));
            SPParity = double.Parse(CsINIForSp.GetInstance().ReadComValue("SerialPort", "Parity"));
        }

        #endregion

        #region 写出INI

        public void INIWrite()
        {
            CsINIForSp.GetInstance().WriteIniValue("SerialPort", "ComPort", SPPort);
            CsINIForSp.GetInstance().WriteIniValue("SerialPort", "BaudRate", SPBaudRate.ToString());
            CsINIForSp.GetInstance().WriteIniValue("SerialPort", "DataBits", SPDataBits.ToString());
            CsINIForSp.GetInstance().WriteIniValue("SerialPort", "StopBits", SPStopBits.ToString());
            CsINIForSp.GetInstance().WriteIniValue("SerialPort", "Parity", SPParity.ToString());
        }

        #endregion


        #region SP通讯必备组件

        #region 串口必备声明

        public List<string> LSPPort { get; set; }
        public List<int> LSPBaudRate { get; set; }
        public List<int> LSPDataBits { get; set; }
        public List<double> LSPStopBits { get; set; }
        public List<double> LSPParity { get; set; }

        private string _SPPort;
        public string SPPort
        {
            get { return _SPPort; }
            set { if (_SPPort != value) { _SPPort = value; RaisePropertyChanged(""); } }
        }

        private int _SPBaudRate;
        public int SPBaudRate
        {
            get { return _SPBaudRate; }
            set { if (_SPBaudRate != value) { _SPBaudRate = value; RaisePropertyChanged(""); } }
        }

        private int _SPDataBits;
        public int SPDataBits
        {
            get { return _SPDataBits; }
            set { if (_SPDataBits != value) { _SPDataBits = value; RaisePropertyChanged(""); } }
        }

        private double _SPStopBits;
        public double SPStopBits
        {
            get { return _SPStopBits; }
            set { if (_SPStopBits != value) { _SPStopBits = value; RaisePropertyChanged(""); } }
        }

        private double _SPParity;
        public double SPParity
        {
            get { return _SPParity; }
            set { if (_SPParity != value) { _SPParity = value; RaisePropertyChanged(""); } }
        }

        private Brush _SPBrush;
        public Brush SPBrush
        {
            get { return _SPBrush; }
            set
            {
                if (_SPBrush != value)
                {
                    _SPBrush = value; RaisePropertyChanged("");
                    BtOpenClose = _SPBrush == Brushes.Lime ? "关闭串口" : "打开串口";
                    IsSPComboBox = _SPBrush == Brushes.Lime ? false : true;
                }
            }
        }

        private bool _IsSPComboBox = true;
        public bool IsSPComboBox
        {
            get { return _IsSPComboBox; }
            set { if (_IsSPComboBox != value) { _IsSPComboBox = value; RaisePropertyChanged(""); } }
        }

        private string _BtOpenClose;
        public string BtOpenClose
        {
            get { return _BtOpenClose; }
            set { if (_BtOpenClose != value) { _BtOpenClose = value; RaisePropertyChanged(""); } }
        }

        private string _DepictInfo;
        public string DepictInfo
        {
            get { return _DepictInfo; }
            set { if (_DepictInfo != value) { _DepictInfo = value; RaisePropertyChanged(""); } }
        }

        //发送区
        private string _SendData = "a5";
        public string SendData
        {
            get { return _SendData; }
            set { if (_SendData != value) { _SendData = value; RaisePropertyChanged(""); } }
        }

        //是否连续发送
        private int _AutoSendNum = 1000;//单位ms
        public int AutoSendNum
        {
            get { return _AutoSendNum; }
            set { if (_AutoSendNum != value) { _AutoSendNum = value; RaisePropertyChanged(""); } }
        }

        private bool _IsAutoSend = false;
        public bool IsAutoSend
        {
            get { return _IsAutoSend; }
            set
            {
                if (_IsAutoSend != value) { _IsAutoSend = value; RaisePropertyChanged(""); }
                if (SPserialPort != null && SPserialPort.IsOpen)
                {
                    if (_IsAutoSend == true)
                        StartAutoSendTimer(AutoSendNum);
                    else
                        StopAutoSendTimer();
                    ((MainWindow)System.Windows.Application.Current.MainWindow).Interface.T.IsEnabled = !_IsAutoSend;
                }
            }
        }

        #endregion

        #region 串口连接初始化

        private void LSPInit()
        {
            LSPPort = SerialPort.GetPortNames().ToList();
            LSPBaudRate = new List<int> { 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
            LSPDataBits = new List<int> { 5, 6, 7, 8 };
            LSPStopBits = new List<double> { 1, 1.5, 2 };
            LSPParity = new List<double> { 1, 1.5, 2 };

            BtOpenClose = "打开串口";
            SPBrush = Brushes.Red;
#if INI
            INIRead();
#elif !INI
            SPPort = "COM1";
            SPBaudRate = 9600;
            SPDataBits = 8;
            SPStopBits = 1;
            SPParity = 1;
#endif

        }

        #endregion

        #region 必备功能组件


        private void RunLog(int nIndex, string strLog)
        {
            switch (nIndex)
            {
                case 0: SystemLog(strLog); break;
                case 1: UserLog(strLog); break;
                default: break;
            }
        }

        private void SystemLog(string strLog)
        {
            DepictInfo = strLog;
        }

        private void UserLog(string strLog)
        {
            MessageBox.Show(strLog, "Tips", MessageBoxButton.OK, MessageBoxImage.Exclamation);
        }

        #region 打开/关闭串口实现

        private SerialPort SPserialPort = null;

        public bool ComOpenClose()
        {
            if (SPserialPort != null && SPserialPort.IsOpen)
                return CloseSP();
            else
                return OpenSP();
        }

        private bool OpenSP()
        {
            try
            {
                SPserialPort = new SerialPort
                {
                    PortName = SPPort,
                    BaudRate = SPBaudRate,
                    DataBits = SPDataBits,
                    StopBits = GetStopBits(SPStopBits.ToString()),
                    Parity = GetParity(SPParity.ToString()),
                    WriteBufferSize = 1048576,   /* 设置串行端口输出缓冲区的大小为1048576字节，即1MB */
                    ReadBufferSize = 2097152,    /* 设置串行端口输入缓冲区的大小为2097152字节，即2MB */
                    Encoding = System.Text.Encoding.GetEncoding("UTF-8"),
                    Handshake = Handshake.None,
                    RtsEnable = true
                };
                SPserialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);//接收响应函数
                SPserialPort.Open();

                if (!SPserialPort.IsOpen)
                {
                    RunLog(0, "串行端口打开失败");
                    return false;
                }
                else
                {
                    SPBrush = Brushes.Lime;
                    RunLog(0, string.Format("{0}打开成功", SPserialPort.PortName));

                    //自动发送定时器
                    if (IsAutoSend == true)
                        StartAutoSendTimer(AutoSendNum);

                    return true;
                }
            }
            catch
            {
                RunLog(0, "串行端口打开失败，请检查线路");
                return false;
            }
        }

        private bool CloseSP()
        {
            try
            {
                if (SPserialPort.IsOpen)
                {
                    StopAutoSendTimer();
                    SPserialPort.Close();
                    SPBrush = Brushes.Red;
                    RunLog(0, "串行端口已关闭");

                    IsAutoSend = false;
                    return SPserialPort.IsOpen;
                }
                else
                {
                    RunLog(0, "串行端口已关闭");

                    return SPserialPort.IsOpen;
                }
            }
            catch
            {
                RunLog(0, "串行端口关闭失败，请检查线路");
                return false;
            }
        }

        #region 停止位和校验位
        private StopBits GetStopBits(string emp)
        {
            StopBits stopBits = StopBits.One;
            switch (emp)
            {
                case "1": stopBits = StopBits.One; break;
                case "2": stopBits = StopBits.Two; break;
                case "1.5": stopBits = StopBits.OnePointFive; break;
                default: break;
            }
            return stopBits;
        }
        private Parity GetParity(string emp)
        {
            Parity parity = Parity.None;
            switch (emp)
            {
                case "0": parity = Parity.None; break;
                case "1": parity = Parity.Odd; break;
                case "2": parity = Parity.Even; break;
                default: break;
            }
            return parity;
        }

        #endregion

        #endregion

        #region 接收实现

        #region byte字节数组转string string转byte字节数组

        private string ConverToString(byte[] data)
        {
            string str;
            StringBuilder stb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                if ((int)data[i] > 15)
                {
                    stb.Append(Convert.ToString(data[i], 16).ToUpper()); //添加字符串
                }
                else  //如果是小于0F需要加个零
                {
                    stb.Append("0" + Convert.ToString(data[i], 16).ToUpper());
                }
                if (i != data.Length - 1)
                    stb.Append(" ");
            }
            str = stb.ToString();
            return str;
        }//byte字节数组转string

        private byte[] StringToConver(string str)
        {
            String[] SendArr = str.Split(' ');//以空格分开
            byte[] decBytes = new byte[SendArr.Length];
            for (int i = 0; i < SendArr.Length; i++)
                decBytes[i] = Convert.ToByte(SendArr[i], 16);
            return decBytes;

        }//string转byte字节数组

        #endregion

        private int nSPComCount = 0;
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)//接收响应函数
        {
            ComRecv();
        }

        private void ComRecv()
        {
            try
            {
                //int nCnt = 0;
                //byte[] Readbuffer = new byte[7];
                //while (nCnt < 7)
                //{
                //    int nRead = SPserialPort.Read(Readbuffer, nCnt, 7 - nCnt);
                //    nCnt += nRead;
                //}

                int nCnt = SPserialPort.BytesToRead;
                byte[] Readbuffer = new byte[nCnt];
                SPserialPort.Read(Readbuffer, 0, nCnt);
                string str = string.Format("第{0}条串口数据：{1}\r\n", ++nSPComCount, ConverToString(Readbuffer));
                MessageBox.Show(str);
                //byte[] Head1byte = { 0xa5 };
                //byte[] Head2byte = { 0x01 };
                //if (Readbuffer[0] == Head1byte[0] && Readbuffer[1] == Head2byte[0])//头校验             
            }
            catch (Exception ex)
            {
                RunLog(0, ex.ToString());
            }
        }

        #endregion

        #region 发送实现

        public void ComSend()
        {
            try
            {
                if (SPserialPort != null && SPserialPort.IsOpen)
                {
                    byte[] decBytes = StringToConver(SendData);
                    SPserialPort.Write(decBytes, 0, decBytes.Length);
                }
                else
                    MessageBox.Show("串口未连接", "提示", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
            catch (Exception ex)
            {
                RunLog(1, "输出字符串错误，末尾不要输入空格和回车");
            }
        }

        #endregion

        #region 清空实现

        public void ClearReceData()
        {
            nSPComCount = 0;
        }

        public void ClearSendData()
        {
            SendData = string.Empty;
        }

        #endregion

        #region 自动发送-定时器

        private DispatcherTimer AutoSendDispatcherTimer = new DispatcherTimer();   /* 自动发送定时器 */
        private void AutoSendDispatcherTimer_Tick(object sender, EventArgs e)//自动发送事件
        {
            ComSend();
        }
        private void InitAutoSendTimer()
        {
            AutoSendDispatcherTimer.IsEnabled = false;
            AutoSendDispatcherTimer.Tick += AutoSendDispatcherTimer_Tick;//定义自动发送事件
        }

        private void StartAutoSendTimer(int interval)//开始发送
        {
            AutoSendDispatcherTimer.IsEnabled = true;
            AutoSendDispatcherTimer.Interval = TimeSpan.FromMilliseconds(interval);
            AutoSendDispatcherTimer.Start();
        }

        private void StopAutoSendTimer()//停止发送
        {
            AutoSendDispatcherTimer.IsEnabled = false;
            AutoSendDispatcherTimer.Stop();
        }

        #endregion

        #endregion

        #endregion
    }





}
